package cn.ztuo.bitrade.consumer;


import cn.ztuo.bitrade.constant.BooleanEnum;
import cn.ztuo.bitrade.constant.IntegrationRecordType;
import cn.ztuo.bitrade.constant.SysConstant;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.service.*;
import cn.ztuo.bitrade.util.CoBoUtils;
import cn.ztuo.bitrade.util.FiworkWalletUtil;
import cn.ztuo.bitrade.util.MessageResult;
import cn.ztuo.bitrade.util.UUIDUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.TreeMap;

import static cn.ztuo.bitrade.util.BigDecimalUtils.*;

@Component
public class FinanceConsumer {
    private Logger logger = LoggerFactory.getLogger(FinanceConsumer.class);
    @Autowired
    private CoinService coinService;
    @Autowired
    private MemberWalletService walletService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private WithdrawRecordService withdrawRecordService;
    @Autowired
    private DataDictionaryService dictionaryService;
    @Autowired
    private IntegrationRecordService integrationRecordService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private MemberGradeService gradeService;
    @Autowired
    private CoBoUtils coBoUtils;
    @Autowired
    private WithdrawRecordService withdrawApplyService;
    @Autowired
    private SysCfService sysCfService;

    private String serviceName = "bitrade-market";


    /**
     * 处理充值消息，key值为币种的名称（注意是全称，如Bitcoin）
     * 弃用
     *
     * @param record
     */
    //@KafkaListener(topics = {"deposit"})
    public void handleDeposit(ConsumerRecord<String, String> record) {
        logger.info("topic={},accessKey={},value={}", record.topic(), record.key(), record.value());
        if (StringUtils.isEmpty(record.value())) {
            return;
        }
        JSONObject json = JSON.parseObject(record.value());
        if (json == null) {
            return;
        }
        BigDecimal amount = json.getBigDecimal("amount");
        String txid = json.getString("txid");
        String address = json.getString("address");
        Coin coin = coinService.findOne(record.key());


        logger.info("coin={}", coin);
        if (coin != null && walletService.findDeposit(address, txid) == null && amount.compareTo(coin.getMinRechargeAmount()) >= 0) {
            //TODO  不明白
            MessageResult mr = walletService.recharge(coin, null,address, amount, txid);
            Long memberId = (Long) mr.getData();
            //处理积分消息 获取币币充值积分赠送比例
            try {
                DataDictionary dictionary = dictionaryService.findByBond(SysConstant.INTEGRATION_GIVING_EXCHANGE_RECHARGE_USDT_RATE);
                Long integration;
                if ("usdt".equalsIgnoreCase(coin.getUnit())) {
                    integration = amount.multiply(new BigDecimal(dictionary.getValue())).setScale(0).longValue();
                } else {
                    String legalCoin = "USD";
                    String unit = coin.getUnit();
                    String url = "http://" + serviceName + "/market/exchange-rate/{legalCoin}/{coin}";
                    ResponseEntity<MessageResult> result = restTemplate.getForEntity(url, MessageResult.class, legalCoin, unit);
                    logger.info("remote call:url={},baseCoin={},unit={},result={}", url, legalCoin, unit, result);
                    if (result.getStatusCode().value() == 200 && result.getBody().getCode() == 0) {
                        BigDecimal rate = new BigDecimal((String) result.getBody().getData());
                        BigDecimal coverUsd = amount.multiply(rate);
                        integration = amount.multiply(new BigDecimal(dictionary.getValue())).setScale(0).longValue();
                    } else {
                        integration = 0L;
                        logger.info("获取币种对usd汇率失败={}", result);
                    }
                }
                //给会员加积分
                Member member = memberService.findOne(memberId);
                Long totalIntegration = member.getIntegration() + integration;
                //判断等级是否满足 V5 V6 不改变等级 只加积分
                MemberGrade grade = gradeService.findOne(member.getMemberGradeId());
                if (grade.getId() != 5L && grade.getId() != 6L) {
                    if (grade.getGradeBound() < totalIntegration) {
                        member.setMemberGradeId(member.getMemberGradeId() + 1);
                    }
                }
                member.setIntegration(totalIntegration);
                IntegrationRecord integrationRecord = new IntegrationRecord();
                integrationRecord.setAmount(integration);
                integrationRecord.setMemberId(member.getId());
                integrationRecord.setCreateTime(new Date());
                integrationRecord.setType(IntegrationRecordType.COIN_RECHARGE_GIVING);
                integrationRecordService.save(integrationRecord);
            } catch (Exception e) {
                logger.info("币币充值积分赠送失败={}", e);
            }
            logger.info("wallet recharge result:{}", mr);
        }
    }

    /**
     * 处理提交请求，自动转账
     * @param record
     */
    @KafkaListener(topics = {"withdraw"})
    public void handleWithdraw(ConsumerRecord<String, String> record) {
        logger.info("topic={},accessKey={},value={}", record.topic(), record.key(), record.value());
        if (StringUtils.isEmpty(record.value())) {
            return;
        }
        JSONObject json = JSON.parseObject(record.value());
        Long withdrawId = json.getLong("withdrawId");
        try {
            Coin coin = coinService.findByUnit((String) json.get("unit"));
            logger.info("coin = {}", coin.toString());
            //该币种是否可以自动提现
            if (coin != null && coin.getCanAutoWithdraw() == BooleanEnum.IS_TRUE) {
                TreeMap<String, Object> params = new TreeMap<>();
                //币种代号.toUpperCase()转换大写
                params.put("coin", record.key().toUpperCase());
                //提现申请Id
                params.put("request_id", withdrawId);
                //提现地址
                params.put("address", json.getString("address"));
                //提现数额, 注意要提前乘以相应币种的decimal, 例如提现1BTC， amount传100000000

                Integer coinPrefixFlag = json.getInteger("coinPrefixFlag");
                String withdrawScale = coinPrefixFlag != null && coinPrefixFlag == 0 ? coin.getWithdrawScale() + "00" : coin.getWithdrawScale();
                BigInteger arriveAmount = mul(json.getBigDecimal("arriveAmount"), new BigDecimal(withdrawScale)).toBigInteger();
                params.put("amount", arriveAmount);
                //交易memo(在某些币种里面也叫tag), 当提现EOS, XRP, IOST等币时，根据情况传入
                params.put("memo", "");
                if (json.getBoolean("isInstation")) {
                    logger.info("内部提币");
                    MemberWallet memberWallet = walletService.findByCoinAndAddress(coin, json.getString("address"));
                    memberWallet = (memberWallet != null) ? memberWallet : walletService.findByCoinAndExtraAddress(coin, json.getString("address"));
                    memberWallet.setBalance(add(memberWallet.getBalance(), json.getBigDecimal("arriveAmount")));
                    if (walletService.save(memberWallet) != null) {
                        //处理成功,data为txid，更新业务订单
                        String uuid = UUIDUtil.getUUID();
                        String str = "yes";
                        withdrawRecordService.withdrawSuccess(withdrawId, uuid, str);
                    }
                } else {

//                    //区块链提币，如果是ETH走提笔，不是ETH走代币提币
//                    //获取ETHlimit限制
//                    String limit = "";
//                    SysCf config = sysCfService.configOneCname("ethlimit");
//                    limit = config.getValue();
//                    if(limit.equals("")||limit==null) limit = "50000";
//                    WithdrawRecord withdrawRecord = withdrawApplyService.findOne(withdrawId);
//                    WithdrawResult withdrawResult = new WithdrawResult();
//                    if(coin.getName().toUpperCase().equals("ETH")) {
//                        withdrawResult = FiworkWalletUtil.withdrawForETH(withdrawRecord.getArrivedAmount(), coin.getExtraAddress(),withdrawRecord.getAddress(),FiworkWalletUtil.getGasPrice(),new BigInteger(limit));
//                    }else{
//                        //代币的提币数量要乘以币种的精度
//                        Coin ethCoin = coinService.findByUnit("ETH");
//                        BigDecimal arrived = mulDown(withdrawRecord.getArrivedAmount(),new BigDecimal(coin.getWithdrawScale()),0);
//                        BigInteger arrivedAmount = new BigInteger(arrived.toString());
//                        withdrawResult = FiworkWalletUtil.withdrawForETHToken(arrivedAmount,ethCoin.getExtraAddress(),coin.getExtraAddress(),withdrawRecord.getAddress(),FiworkWalletUtil.getGasPrice(),new BigInteger(limit));
//                    }
//                    logger.info("result = {}", withdrawResult);
//                    Boolean success = withdrawResult.getSuccess();
//                    if (success) {
//                        logger.info("区块链提币成功");
//                        //处理成功,data为txid，更新业务订单
////                        String uuid = UUIDUtil.getUUID();
//                        String uuid = withdrawResult.getEthSendTransaction().toString();
//                        String str = "no";
//                        withdrawRecordService.withdrawSuccess(withdrawId, uuid, str);
//                    } else {
//                        logger.info("====================== 区块链提币失败，转为人工处理 ==================================");
//                        //自动转账失败，转为人工处理
//                        withdrawRecordService.withdrawFail(withdrawId);
//                    }
                   // withdrawRecordService.withdrawFail(withdrawId);
                    withdrawRecordService.autoWithdrawFail(withdrawId);
                }
            }else {
                logger.info("不支持自动提币，转为人工审核！");
                withdrawRecordService.autoWithdrawFail(withdrawId);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("auto withdraw failed,error={}", e.getMessage());
            //自动转账失败，转为人工处理
            withdrawRecordService.autoWithdrawFail(withdrawId);
        }
    }

/*    *//**
     * 处理提交请求，自动转账
     * @param record
     *//*
    @KafkaListener(topics = {"withdraw"})
    public void handleWithdraw(ConsumerRecord<String, String> record) {
        logger.info("topic={},accessKey={},value={}", record.topic(), record.key(), record.value());
        if (StringUtils.isEmpty(record.value())) {
            return;
        }
        JSONObject json = JSON.parseObject(record.value());
        Long withdrawId = json.getLong("withdrawId");
        try {
            Coin coin = coinService.findByUnit((String) json.get("unit"));
            logger.info("coin = {}", coin.toString());
            //该币种是否可以自动提现
            if (coin != null && coin.getCanAutoWithdraw() == BooleanEnum.IS_TRUE) {
                TreeMap<String, Object> params = new TreeMap<>();
                //币种代号.toUpperCase()转换大写
                params.put("coin", record.key().toUpperCase());
                //提现申请Id
                params.put("request_id", withdrawId);
                //提现地址
                params.put("address", json.getString("address"));
                //提现数额, 注意要提前乘以相应币种的decimal, 例如提现1BTC， amount传100000000

                Integer coinPrefixFlag = json.getInteger("coinPrefixFlag");
                String withdrawScale = coinPrefixFlag != null && coinPrefixFlag == 0 ? coin.getWithdrawScale() + "00" : coin.getWithdrawScale();
                BigInteger arriveAmount = mul(json.getBigDecimal("arriveAmount"), new BigDecimal(withdrawScale)).toBigInteger();
                params.put("amount", arriveAmount);
                //交易memo(在某些币种里面也叫tag), 当提现EOS, XRP, IOST等币时，根据情况传入
                params.put("memo", "");

                if (json.getBoolean("isInstation")) {
                    logger.info("内部提币");
                    MemberWallet memberWallet = walletService.findByCoinAndAddress(coin, json.getString("address"));
                    memberWallet = (memberWallet != null) ? memberWallet : walletService.findByCoinAndExtraAddress(coin, json.getString("address"));
                    memberWallet.setBalance(add(memberWallet.getBalance(), json.getBigDecimal("arriveAmount")));
                    if (walletService.save(memberWallet) != null) {
                        //处理成功,data为txid，更新业务订单
                        String uuid = UUIDUtil.getUUID();
                        String str = "yes";
                        withdrawRecordService.withdrawSuccess(withdrawId, uuid, str);
                    }
                } else {
                    logger.info("cobo提币");
                    //dia调用cobo接口开始提币
                    JSONObject jsonObject = coBoUtils.cashWithdrawal(params);
                    logger.info("result = {}", jsonObject);
                    Boolean success = jsonObject.getBoolean("success");
                    if (success) {
                        //处理成功,data为txid，更新业务订单
                        String uuid = UUIDUtil.getUUID();
                        String str = "no";
                        withdrawRecordService.withdrawSuccess(withdrawId, uuid, str);
                    } else {
                        logger.info("====================== 自动转账失败，转为人工处理 ==================================");
                        //自动转账失败，转为人工处理
                        withdrawRecordService.withdrawFail(withdrawId);
                    }
                }
            }else {
                logger.info("不支持自动提币，转为人工审核！");
                withdrawRecordService.autoWithdrawFail(withdrawId);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("auto withdraw failed,error={}", e.getMessage());
            //自动转账失败，转为人工处理
            withdrawRecordService.autoWithdrawFail(withdrawId);
        }
    }*/

    /**
     * 方法弃用
     * 异步打钱后返回状态
     *
     * @param record
     */
   /* @KafkaListener(topics = {"withdraw-notify"})
    public void withdrawNotify(ConsumerRecord<String, String> record) {
        logger.info("topic={},accessKey={},value={}", record.topic(), record.key(), record.value());
        if (StringUtils.isEmpty(record.value())) {
            return;
        }
        JSONObject json = JSON.parseObject(record.value());
        Long withdrawId = json.getLong("withdrawId");
        WithdrawRecord withdrawRecord = withdrawRecordService.findOne(withdrawId);
        if (withdrawRecord == null) {
            return;
        }
        String txid = json.getString("txid");
        int status = json.getInteger("status");
        //转账失败，状态变回等待放币
        if (status == 0) {
            withdrawRecord.setStatus(WithdrawStatus.WAITING);
            withdrawRecordService.save(withdrawRecord);
        } else if (status == 1) {
            //withdrawRecordService.withdrawSuccess(withdrawId, txid);
        }
    }*/
}
